package com.hhq.android_web.tools;


import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.os.Build;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.hhq.android_web.R;

import java.io.InputStream;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;


public class GifImageView extends AppCompatImageView {
    private static final String TAG = "ImageView";
    private static final int DEFAULT_MOVIE_DURATION = 2000;
    private Movie mMovie;
    private long mMovieStart;
    private int mCurrentAnimationTime;

    /**
     * Scaling factor to fit the animation within view bounds.
     */
    private float mScale = 1;
    private boolean mVisible = true;

    public GifImageView(Context context) {
        this(context, null);
    }

    public GifImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public GifImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setViewAttributes();
    }

    @SuppressLint("NewApi")
    public void setViewAttributes() {
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mMovie != null) {
            updateAnimationTime();
            drawMovieFrame(canvas);
            invalidateView();
        }
    }

    /**
     * Draw current GIF frame
     */
    private void drawMovieFrame(Canvas canvas) {
        mMovie.setTime(mCurrentAnimationTime);
        canvas.save(); // Canvas.ALL_SAVE_FLAG
        canvas.scale(mScale, mScale);
        mMovie.draw(canvas, 0, 0);
        canvas.restore();
    }

    /**
     * Calculate current animation time
     */
    private void updateAnimationTime() {
        long now = android.os.SystemClock.uptimeMillis();

        if (mMovieStart == 0) {
            mMovieStart = now;
        }

        int dur = mMovie.duration();

        if (dur == 0) {
            dur = DEFAULT_MOVIE_DURATION;
        }

        mCurrentAnimationTime = (int) ((now - mMovieStart) % dur);
    }

    /**
     * Invalidates view only if it is visible.
     */
    @SuppressLint("NewApi")
    private void invalidateView() {
        if (mVisible) {
            postInvalidateOnAnimation();
        }
    }

    @SuppressLint("NewApi")
    @Override
    public void onScreenStateChanged(int screenState) {
        super.onScreenStateChanged(screenState);
        mVisible = screenState == SCREEN_STATE_ON;
        invalidateView();
    }

    @SuppressLint("NewApi")
    @Override
    protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        mVisible = visibility == View.VISIBLE;
        invalidateView();
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        mVisible = visibility == View.VISIBLE;
        invalidateView();
    }

    public void setMovieResource(int movieResId) {
        mMovie = Movie.decodeStream(getResources().openRawResource(movieResId));
        requestLayout();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (changed && mMovie != null) {
            float scaleW = (float) getWidth() / mMovie.width();
            float scaleH = (float) getHeight() / mMovie.height();
            mScale = Math.min(scaleH, scaleW);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (mMovie != null) {
            int mMeasureWidth;
            int mMeasureHeight;
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            if (widthMode == MeasureSpec.AT_MOST) {
                Log.e(TAG, "---moviewidth before" + mMovie.width());
                int movieWidth = mMovie.width();
                mMeasureWidth = Math.min(movieWidth, widthSize);
                Log.e(TAG, "---moviewidth after" + mMovie.width());
            } else {
                mMeasureWidth = widthSize;
            }
            if (heightMode == MeasureSpec.AT_MOST) {
                Log.e(TAG, "---height " + mMovie.height());
                int movieHieght = mMovie.height();
                mMeasureHeight = Math.min(movieHieght, heightSize);

            } else {
                mMeasureHeight = heightSize;
            }
            Log.e(TAG, "--wi : " + mMeasureWidth + "  h  : " + mMeasureHeight);
            setMeasuredDimension(mMeasureWidth, mMeasureHeight);
        }
    }
}